package com.jl.smartcard.ui.views.cardlist;

import java.io.File;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.IConsoleConstants;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.ide.FileStoreEditorInput;
import org.eclipse.ui.internal.console.ConsoleView;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.wb.swt.SWTResourceManager;

import com.jl.card.Card;
import com.jl.card.Card.CmdListenner;
import com.jl.card.CardManager;
import com.jl.card.JL;
import com.jl.card.tracer.EditorTracer;
import com.jl.js.console.ConsoleShell;
import com.jl.js.console.ConsoleUtil;
import com.jl.smartcard.ui.ImageShop;
import com.jl.smartcard.ui.SmartCardUI;
import com.jl.smartcard.ui.console.CardConsoleFactory;
import com.jl.smartcard.ui.editors.scr.ScrEditor;
import com.jl.smartcard.ui.views.project.ProjectConfig;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.wb.swt.ResourceManager;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;

public class SmartCardListView extends ViewPart {

	public static final String ID = "com.jl.smartcard.ui.views.cardlist.SmartCardListView"; //$NON-NLS-1$
	private Tree tree;
	private Action refresh;
	private Action connect;
	private Action showCmd;
	private Action disconnect;
	
	private TreeColumn trclmnCommand;
	private TableViewer tableViewer;
	private TreeViewer treeViewer;
	private Table table;
	private TreeContentProvider treeProvider;
	private TreeModel model;

	public SmartCardListView() {
		treeProvider = new TreeContentProvider();
		model = new TreeModel();
		model.setView(this);
	}

	/**
	 * Create contents of the view part.
	 * @param parent
	 */
	@Override
	public void createPartControl(Composite parent) {
		Composite container = new Composite(parent, SWT.NONE);
		container.setLayout(new FillLayout(SWT.HORIZONTAL));
		
		SashForm sashForm = new SashForm(container, SWT.NONE);
		sashForm.setSashWidth(1);
		sashForm.setOrientation(SWT.VERTICAL);
		
		tableViewer = new TableViewer(sashForm, SWT.FULL_SELECTION);
		table = tableViewer.getTable();
		tableViewer.setContentProvider(new TableContentProvider());
		tableViewer.setLabelProvider(new TableLabelProvider());
		tableViewer.setSorter(new NameSorter());
		tableViewer.setInput(getViewSite());
		tableViewer.addDoubleClickListener(new IDoubleClickListener() {
			@Override
			public void doubleClick(DoubleClickEvent event) {
				event_double_clicked_table_viewer();
			}
		});
		
		Composite composite = new Composite(sashForm, SWT.NONE);
		GridLayout gl_composite = new GridLayout(1, false);
		gl_composite.verticalSpacing = 0;
		gl_composite.marginWidth = 0;
		gl_composite.marginHeight = 0;
		gl_composite.horizontalSpacing = 0;
		composite.setLayout(gl_composite);
		
		ToolBar toolBar = new ToolBar(composite, SWT.FLAT | SWT.RIGHT);
		toolBar.setLocation(new Point(100, 0));
		toolBar.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, false, 1, 1));
		
		ToolItem tltmClear = new ToolItem(toolBar, SWT.NONE);
		tltmClear.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				event_click_btn_clear();
			}
		});
		tltmClear.setImage(ResourceManager.getPluginImage("com.jl.smartcard.ui", "icons/abs/clear_16.png"));
		
		treeViewer = new TreeViewer(composite, SWT.NONE);
		treeViewer.setContentProvider(this.treeProvider );
		treeViewer.setLabelProvider(new TreeLabelProvider());
		treeViewer.setInput(model);
		tree = treeViewer.getTree();
		tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		tree.setFont(SWTResourceManager.getFont("Courier New", 11, SWT.NORMAL));
		sashForm.setWeights(new int[] {85, 383});

		createActions();
		createTableListenner();
		initializeToolBar();
		initializeMenu();
	}
	
	protected void event_click_btn_clear() {
		model.clear();
		refreshTree();
	}

	protected void event_double_clicked_table_viewer() {
		ISelection selection = tableViewer.getSelection();
		Object obj = ((IStructuredSelection) selection)
				.getFirstElement();
		openConsole(obj.toString());
	}
	
	/**
	 * @param cardName
	 */
	protected void openConsole(String cardName) {
		boolean exist = CardConsoleFactory.exist(cardName);
		if (exist) {
			return;
		}
		Card card = new Card(cardName);
		card.open();
		if (card.getStatus() != JL.CARD_STATUS_CONNECTED) {
			MessageDialog.openInformation(tableViewer.getControl().getShell(),
					"Error", "Can't connect the card ");
			card = null;
			return;
		}
		card.addCmdListenner(model);
		
		// CardManager.getInstance(false).registe(card);
		CardConsoleFactory.openConsole(cardName);
		IOConsole console = CardConsoleFactory.getConsole(cardName);
		
		
		final ConsoleView vp = (ConsoleView) PlatformUI.getWorkbench()
				.getActiveWorkbenchWindow().getActivePage()
				.findView(IConsoleConstants.ID_CONSOLE_VIEW);
		
		final ConsoleShell consoleshell = new ConsoleShell(card, console);
		
		if (vp != null) {
			vp.getViewSite().getPage().addPartListener(new IPartListener() {
				
				private IActionBars bars = vp.getViewSite().getActionBars();
				IToolBarManager mgr = bars.getToolBarManager();
				Action actionLeft = new LeftAction(consoleshell);
				Action actionRight = new RightAction(consoleshell);
				IContributionItem item = new ActionContributionItem(actionLeft);
				IContributionItem item2 = new ActionContributionItem(actionRight);
				@Override
				public void partOpened(IWorkbenchPart part) {
					actionLeft.setImageDescriptor(ImageShop.getDescriptor("left_16"));
					mgr.insertBefore("launchGroup", item);
					actionRight.setImageDescriptor(ImageShop.getDescriptor("right_16"));
					mgr.insertBefore("launchGroup", item2);
				}
				
				@Override
				public void partDeactivated(IWorkbenchPart part) {
					// TODO Auto-generated method stub
					
				}
				
				@Override
				public void partClosed(IWorkbenchPart part) {
					mgr.remove(item);
					mgr.remove(item2);
				}
				
				@Override
				public void partBroughtToTop(IWorkbenchPart part) {
					// TODO Auto-generated method stub
					
				}
				
				@Override
				public void partActivated(IWorkbenchPart part) {
					// TODO Auto-generated method stub
					
				}
			});
			vp.setFocus();
		}
		ScrEditor e = (ScrEditor) openScrEditor(cardName);
		EditorTracer tracer = new EditorTracer(e);
		consoleshell.setEditorTracer(tracer);
		Thread t = new Thread(consoleshell);
		consoleshell.initLogger();
		ConsoleUtil.register(cardName, consoleshell);
		t.start();
	}
	
	protected IEditorPart openScrEditor(String name) {
		// openScrEditor
		File file = ProjectConfig.getDEFAULTLog(name + ".scr");
		try {
			IFileStore fileStore = EFS.getStore(file.toURI());
			IWorkbenchPage page = getSite().getPage();
			IEditorPart scr = page.openEditor(new FileStoreEditorInput(
					fileStore), SmartCardUI.ID_EDITOR_SCR, false);
			return scr;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Create the actions.
	 */
	private void createActions() {
		refresh = new Action() {
			@Override
			public void run() {
				CardConsoleFactory.closeAll();
				CardManager.getInstance().removeAll();
				tableViewer.refresh(true);
			}
		};
		refresh.setText("refresh");
		refresh.setToolTipText("refresh card list");
		refresh.setImageDescriptor(ImageShop.getDescriptor("refresh_16"));
		//
		disconnect = new Action() {
			@Override
			public void run() {
				IStructuredSelection selected = (IStructuredSelection) tableViewer.getSelection();
				if(selected != null){
					if(!selected.isEmpty()){
						String name = (String) selected.getFirstElement();
						Card card = CardManager.getInstance().getCardInstanceByName(name);
						if(card != null){
							CardConsoleFactory.closeConsole(name);
							card.close();
						}
					}
				}
				disconnect.setEnabled(false);
			}
		};
		disconnect.setText("disconnect");
		disconnect.setToolTipText("Disconnect the selected card");
		disconnect.setImageDescriptor(ImageShop.getDescriptor("disconnect_16"));
		
		
		showCmd = new Action() {
			@Override
			public void run() {
				treeViewer.refresh(true);
			}
		};
		showCmd.setText("Refresh Command");
		showCmd.setImageDescriptor(ImageShop.getDescriptor("connect_16"));
	}
	
	
	private void createTableListenner(){
		tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
			
			@Override
			public void selectionChanged(SelectionChangedEvent event) {
				// TODO Auto-generated method stub
				IStructuredSelection selected = (IStructuredSelection) event.getSelection();
				if(selected != null){
					if(!selected.isEmpty()){
						String name = (String) selected.getFirstElement();
						Card card = CardManager.getInstance().getCardInstanceByName(name);
						if(card != null){
							if(card.getStatus() == JL.CARD_STATUS_CONNECTED){
								disconnect.setEnabled(true);
							}else{
								disconnect.setEnabled(false);
							}
						}else{
							disconnect.setEnabled(false);
						}
					}
				}
			}
		});
		
	}

	/**
	 * Initialize the toolbar.
	 */
	private void initializeToolBar() {
		IToolBarManager toolbarManager = getViewSite().getActionBars()
				.getToolBarManager();
		toolbarManager.add(disconnect);
		toolbarManager.add(refresh);
		//toolbarManager.add(showCmd);
	}

	/**
	 * Initialize the menu.
	 */
	private void initializeMenu() {
		IMenuManager menuManager = getViewSite().getActionBars()
				.getMenuManager();
	}

	@Override
	public void setFocus() {
		this.tableViewer.getControl().setFocus();
	}

	public void refreshTree() {
		getSite().getShell().getDisplay().syncExec(new Runnable() {
			@Override
			public void run() {
				showCmd.run();
			}
		});
	}
}

class TableContentProvider implements IStructuredContentProvider {
	@Override
	public void inputChanged(Viewer v, Object oldInput, Object newInput) {
	}

	@Override
	public void dispose() {
	}

	@Override
	public Object[] getElements(Object parent) {
		CardManager.refresh();
		return CardManager.getAllCardsName();
	}
}

class TableLabelProvider extends LabelProvider implements
		ITableLabelProvider {
	@Override
	public String getColumnText(Object obj, int index) {
		return getText(obj);
	}

	@Override
	public Image getColumnImage(Object obj, int index) {
		return ImageShop.get("card_16");
	}
}

class NameSorter extends ViewerSorter {
}
